package pers.hll.processor;

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import pers.hll.annotation.ConstantClass;
import pers.hll.visitor.ConstantClassVisitor;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.util.Set;

@SupportedAnnotationTypes("pers.hll.annotation.ConstantClass")
@SupportedSourceVersion(SourceVersion.RELEASE_17)
public class ConstantClassProcessor extends AbstractProcessor {

    private Trees trees;

    @Override
    public synchronized void init(javax.annotation.processing.ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        trees = Trees.instance(this.processingEnv);
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (Element element : roundEnv.getElementsAnnotatedWith(ConstantClass.class)) {
            TypeElement typeElement = (TypeElement) element;
            TreePath path = trees.getPath(typeElement);
            CompilationUnitTree compilationUnitTree = path.getCompilationUnit();
            String sourceCode = compilationUnitTree.toString();
            try {
                CompilationUnit cu = StaticJavaParser.parse(sourceCode);
                LexicalPreservingPrinter.setup(cu);
                ConstantClassVisitor visitor = new ConstantClassVisitor();
                visitor.visit(cu, null);
                visitor.removeImportsAfterVisit();
                String modifiedCode = LexicalPreservingPrinter.print(cu);
                // when another project import this project, it will print the modifiedCode by `mvn compile`
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "hello lombok-ext: " + modifiedCode);
                // it can't write modifiedCode into xxx.class file
                //processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, modifiedCode);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return true;
    }
}